package com.lzxuni.common.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lzxuni.common.annotation.SysLog;
import com.lzxuni.common.exception.LzxException;
import com.lzxuni.common.utils.Constant;
import com.lzxuni.common.utils.R;
import com.lzxuni.common.utils.StringUtils;
import com.lzxuni.common.utils.date.DateUtil;
import com.lzxuni.common.utils.web.HttpContextUtils;
import com.lzxuni.common.utils.web.RequestUtils;
import com.lzxuni.modules.shiro.ShiroUtils;
import com.lzxuni.modules.system.entity.Log;
import com.lzxuni.modules.system.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;


/**
 * 系统日志，切面处理类
 *
 * @author 孙志强

 * @date 2017年3月8日 上午11:07:35
 */
@Aspect
@Component
public class SysLogAspect {
	protected Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
	@Autowired
	private LogService logService;
//	@Autowired
//	private MailConfig mailConfig;

	@Pointcut("@annotation(com.lzxuni.common.annotation.SysLog)")
	public void logPointCut() {

	}
	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		Long beginTime = System.currentTimeMillis();
		Long time = null;
				//执行方法
		Object result =null ;
		String operationResult = Constant.SCUCCESS;
		try {
			result = point.proceed();
			//执行时长(毫秒)
			time = System.currentTimeMillis() - beginTime;
			saveSysLog(point,operationResult, time,result,null);
		}catch (Exception e){
			operationResult = Constant.FAIL;
			//执行时长(毫秒)
			time = System.currentTimeMillis() - beginTime;
			//保存日志
			try {
				saveSysLog(point,operationResult, time,"",e);
			} catch (Exception e1) {
				logger.error("记录日志报错，请查找原因"+ e1.getMessage());
				e1.printStackTrace();
			}
			if(e instanceof LzxException){
				throw new LzxException(e.getMessage());
			}else{
				throw new Exception(e);
			}

		}
		return result;
	}
	private void saveSysLog(JoinPoint joinPoint,String operationResult,long time,Object result,Exception e) {
		//获取request
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		//获得注解元素
		SysLog syslog = method.getAnnotation(SysLog.class);


		Log log= new Log();
		//分类Id 1-登陆2-访问3-操作4-异常
		if(operationResult.equals(Constant.SCUCCESS)){
			log.setCategoryId(syslog.categoryId());
		}else {
			log.setCategoryId(4);
		}

		//操作时间
		log.setOperateTime(new Date());
		String username;
		try {
			username = ShiroUtils.getUser().getUsername()+"("+ ShiroUtils.getUser().getRealName()+")";
			log.setOperateUserId(ShiroUtils.getUser().getUserId());
		} catch (Exception e1) {
			username="接口";
		}
		log.setOperateUsername(username);
		log.setOperateType(syslog.operateType());
		log.setModule(syslog.module());
		log.setIpAddress(RequestUtils.getIpAddr(request));
		//保存ip所在地采用异步操作
		try {
			log.setHost("操作系统："+System.getProperty("os.name")+",主机名称："+InetAddress.getLocalHost().getHostName());
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		log.setBrowser(RequestUtils.getOsAndBrowserInfo(request));
		if(operationResult.equals(Constant.SCUCCESS)){
			if(result instanceof R){
				R r = (R) result;
				String s = JSONObject.toJSONString(r);
				JSONObject jsonObject = JSON.parseObject(s);
				Integer code = (Integer) jsonObject.get("code");
				String info = (String) jsonObject.get("info");
//				if(code ==200){
					log.setExecuteResult(1);
					if(log.getCategoryId()==1 || log.getCategoryId()==3){
						log.setExecuteResultJson(s);
					}else if(log.getCategoryId()==2){
						log.setExecuteResultJson("访问地址："+ RequestUtils.getLocation(request));
					}
//				}else{
//					log.setExecuteResult(0);
//				}
				log.setExecuteResultJson(s);
			}else{
				//正常跳转页面
				log.setExecuteResult(1);
			}
		}else{
			log.setExecuteResult(0);
		}
		log.setUrl(RequestUtils.getLocation(request));
		//请求的方法名
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		log.setMethod(className + "." + methodName + "()");
		//请求的参数
		Object[] args = joinPoint.getArgs();
		String params="";
		if(args!=null && args.length>0){
			for (int i = 0; i < args.length; i++) {
				if(!(args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse)){
					params = params+","+JSON.toJSONString(args[i]);
				}
			}
			if(StringUtils.isNotEmpty(params)){
				params = params.substring(1, params.length());
			}
		}
		log.setParams(params);
		log.setTime(time);
		if(log.getExecuteResult()==0 && log.getCategoryId()!=1){
			//调试信息
			String executeResultJson = "1. 调试: &gt;&gt; 操作时间: "+ DateUtil.DateToString(log.getOperateTime(),"YYYY-MM-dd HH:mm:ss")+" 操作人: "+username+"（"+username+"） \n" +
					"2. 地址: "+request.getRequestURI()+"    \n" +
					"3. 类名: "+log.getMethod()+" \n" +
					"4. 主机:    Ip  : "+log.getIpAddress()+"   浏览器: "+ RequestUtils.getOsAndBrowserInfo(request)+"    \n" +
					"5. 异常: "+e.getClass().getName()+"-"+e.getMessage()+"!";

			log.setExecuteResultJson(executeResultJson);
			//异常信息
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			e.printStackTrace(new PrintStream(baos));
			String exception = baos.toString();
			log.setOperationContentExt(exception);
//			sendMail(log);
		}
//		保存系统日志
		logService.save(log);
		setIpAddressName(log);
	}

	private void setIpAddressName(Log log) {
		new Thread(() -> {
			log.setIpAddressName(RequestUtils.getAddressByIp(log.getIpAddress()));
			logService.updateById(log);
		}).start();
	}
//	private void sendMail(Log log) {
//		new Thread(() -> {
//			mailConfig.sendMail("金融平台监控信息" + log.getModule(), log.getOperationContentExt());
//		}).start();
//	}




}
